﻿using TimerJobServer.Common.Mina;
using log4net;
using log4net.Repository.Hierarchy;
using Mina.Core.Service;
using Mina.Core.Session;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;

namespace TimerJobServer
{
    /// <summary>
    /// 服务处理
    /// </summary>
    public class MinaServerHandler : IoHandlerAdapter
    {
        private readonly ILog logger = LogManager.GetLogger(typeof(MinaServerHandler));

        public  IDictionary<IPEndPoint, IoSession> sessions = new ConcurrentDictionary<IPEndPoint, IoSession>();
        public void Broadcast(String message)
        {
            foreach (IoSession session in sessions.Keys)
            {
                if (session.Connected)
                    session.Write("BROADCAST OK " + message);
            }
        }

        const string KEY_SESSION_CLIENT_IPEndPoint = "KEY_SESSION_CLIENT_IPEndPoint";
        public override void SessionCreated(IoSession session)
        {
            var remote = (System.Net.IPEndPoint)(session.RemoteEndPoint);
            session.SetAttribute(KEY_SESSION_CLIENT_IPEndPoint, remote);
            sessions.Add(remote, session); //添加session
            logger.Info(string.Format("建立连接:IP:{0},端口:{1}",remote.Address,remote.Port));
        }

        public override void SessionOpened(IoSession session)
        {
            logger.Info("打开连接:");
        }

        public override void SessionClosed(IoSession session)
        {
            System.Net.IPEndPoint clientIP = session.GetAttribute<System.Net.IPEndPoint>(KEY_SESSION_CLIENT_IPEndPoint);

            foreach (var item in sessions)
            {
                var key = item.Key;
                if (key.Address==clientIP.Address)
                {
                    sessions.Remove(key);
                }
            }

            logger.Info("关闭连接:" + session);
        }
        /// <summary>
        /// Trap exceptions.
        /// </summary>
        public override void ExceptionCaught(IoSession session, Exception cause)
        {
            logger.Error(cause);
            session.Close(true);
        }

        /// <summary>
        /// If the message is 'quit', we exit by closing the session. Otherwise,
        /// we return the current date.
        /// </summary>
        public override void MessageReceived(IoSession session, Object message)
        {
            try
            {
                System.Net.IPEndPoint clientIP = session.GetAttribute<System.Net.IPEndPoint>(KEY_SESSION_CLIENT_IPEndPoint);
                
                TransferObj tran = (TransferObj)message;
                switch (tran.Type)
                {
                    case TranType.Get:
                        break;
                    case TranType.Put:
                        break;
                    case TranType.Log:
                        break;
                    case TranType.GetJobList:
                        GetJobList(session,tran);
                        break;
                    case TranType.AddJob:
                        AddJob(session, tran);
                        break;
                    case TranType.RemoveJob:
                        RemoveJob(session, tran);
                        break;
                    case TranType.UpdateJob:
                        UpdateJob(session, tran);
                        break;
                    case TranType.ExeJob:
                        ExeJob(session, tran);
                        break;
                    case TranType.GetRemoteFiles:
                        GetRemoteFiles(session, tran);
                        break;
                    case TranType.ReadRemoteFile:
                        ReadRemoteFile(session, tran);
                        break;
                    case TranType.SaveRemoteFile:
                        SaveRemoteFile(session, tran);
                        break;
                    case TranType.EnableJobs:
                        EnableJobs(session, tran);
                        break;
                    case TranType.DisableJobs:
                        DisableJobs(session, tran);
                        break;
                    default:
                        break;
                }
                //logger.Info(clientIP.Address + ":" + clientIP.Port+ tran.Type);
                ////tran.Message = DateTime.Now.ToString();
                //// Send the current date back to the client
                //session.Write(tran);
            }
            catch (Exception ex)
            {
                logger.Error(ex);
                throw;
            }
        }

        /// <summary>
        ///  启用所有任务
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tran">Jobs 必须</param>
        private void EnableJobs(IoSession session, TransferObj tran)
        {
            //更新任务
            QuartzJobServer.EnableJobs(tran.Jobs);
            ReturnJobList(session);
        }

        /// <summary>
        /// 禁用所有任务
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tran">Jobs必须</param>
        private void DisableJobs(IoSession session, TransferObj tran)
        {
            //更新任务
            QuartzJobServer.DisableJobs(tran.Jobs);
            ReturnJobList(session);
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tran"></param>
        private void SaveRemoteFile(IoSession session, TransferObj tran)
        {
            try
            {
                string path = tran.FileFullPath;
                string content = tran.FileContent;
                FileInfo fi = new FileInfo(path);
                //logger.Debug(path);
                if (fi.Exists)
                {
                   var type =  Common.FileEncoding.EncodingType.GetType(path);

                    System.IO.File.WriteAllText(path, content,type);
                    //logger.Debug(sb.ToString());
                    //FileStream fileStream = new FileStream(path,FileMode.Open,FileAccess.Read,FileShare.ReadWrite);
                    //返回任务列表
                   // session.Write(tran);
                }
            }
            catch (Exception ex)
            {
                logger.Fatal(ex.ToString());
                //throw;
            }
           
        }

        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tran"></param>
        private void ReadRemoteFile(IoSession session, TransferObj tran)
        {
            try
            {
                string path =  tran.FileFullPath;
                FileInfo fi = new FileInfo(path);
                //logger.Debug(path);

                if (fi.Exists)
                {
                    //StringBuilder sb = new StringBuilder();
                    //using (FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    //{
                    //    StreamReader sr = new StreamReader(fileStream);
                    //    string s;
                    //    while ((s = sr.ReadLine()) != null)
                    //    {
                    //        sb.Append(s);
                    //    }

                    //}
                    //FileStream fileStream = new FileStream(path,FileMode.Open,FileAccess.Read,FileShare.ReadWrite);

                    var type = Common.FileEncoding.EncodingType.GetType(path);

                    string text = System.IO.File.ReadAllText(path,type);
                    //logger.Debug(sb.ToString());
                    //FileStream fileStream = new FileStream(path,FileMode.Open,FileAccess.Read,FileShare.ReadWrite);
                    //返回任务列表
                    tran.FileContent = text;
                    //logger.Debug(text.Length);
                    session.Write(tran);
                }

            }
            catch (Exception ex)
            {
                logger.Fatal(ex.ToString());
                //throw;
            }
        }

        /// <summary>
        /// 获取远程文件列表
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tran"></param>
        private void GetRemoteFiles(IoSession session, TransferObj tran)
        {
            try
            {
                //起始目录
                string RootPath = AppDomain.CurrentDomain.BaseDirectory;
                DirectoryInfo directoryInfo = new DirectoryInfo(RootPath);
                var directory = new ObservableCollection<DirectoryRecord>();

                var directoryRoot = new DirectoryRecord();
                directoryRoot.FileName = directoryInfo.Name;
                directoryRoot.FileFullName = directoryInfo.FullName;
                directoryRoot.IsExpanded = true;
                AddFile(directoryInfo, directoryRoot);
                directory.Add(directoryRoot);

                //返回任务列表
                TransferObj transferObj = new TransferObj()
                {
                    Type = TranType.GetRemoteFiles,
                    DirectoryRecords = directory
                };
                session.Write(transferObj);

            }
            catch (Exception ex)
            {
                logger.Fatal(ex.ToString());
                throw;
            }
            
        }

        private void AddFile(DirectoryInfo directoryInfo, DirectoryRecord record)
        {
            if (directoryInfo.Exists)
            {
                foreach (var dir in directoryInfo.GetDirectories())
                {
                    var dircon = new DirectoryRecord()
                    {
                        FileName = dir.Name,
                        FileFullName = dir.FullName
                    };
                    record.Nodes.Add(dircon);
                    AddFile(dir, dircon);
                }

                foreach (var file in directoryInfo.GetFiles())
                {
                    record.Nodes.Add(new DirectoryRecord()
                    {
                        FileName = file.Name,
                        FileFullName = file.FullName
                    });
                }
            }
        }

        private void ExeJob(IoSession session, TransferObj tran)
        {
            QuartzJobServer.ExeJob(tran.Job);
        }

        private void UpdateJob(IoSession session, TransferObj tran)
        {
            //更新任务
            QuartzJobServer.UpdateJob(tran.Job);
            ReturnJobList(session);
        }

        private void RemoveJob(IoSession session, TransferObj tran)
        {
            //删除任务
            QuartzJobServer.RemoveJob(tran.Job);
            ReturnJobList(session);
        }

        /// <summary>
        /// 增加任务功能
        /// </summary>
        /// <param name="session"></param>
        /// <param name="tran"></param>
        private void AddJob(IoSession session, TransferObj tran)
        {
            //添加任务
            QuartzJobServer.AddJob(tran.Job);
            ReturnJobList(session);
        }


        /// <summary>
        /// 返回任务列表
        /// </summary>
        /// <param name="session"></param>
        private void ReturnJobList(IoSession session)
        {
            //返回任务列表
            TransferObj transferObj = new TransferObj()
            {
                Type = TranType.GetJobList,
                Jobs = QuartzJobServer.Jobs
            };
            session.Write(transferObj);
        }

        /// <summary>
        /// 读取当前工作信息
        /// </summary>
        private void GetJobList(IoSession session,TransferObj tran)
        {
           var jobs =  QuartzJobServer.Jobs;
            tran.Jobs = jobs;
            session.Write(tran);
        }

        /// <summary>
        /// On idle, we just write a message on the console
        /// </summary>
        public override void SessionIdle(IoSession session, IdleStatus status)
        {
            logger.Info("IDLE " + session.GetIdleCount(status));
        }

    }
}
